home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Diamond Collection / The Diamond Collection (Software Vault)(Digital Impact).ISO / cdr13 / veced100.zip / CONVLOAD.CPP < prev    next >
C/C++ Source or Header  |  1995-01-19  |  28KB  |  981 lines

  1. // This module contains routines to perform file operations and stuff
  2. #include <dos.h>
  3. #include <conio.h>
  4. #include <stdio.h>
  5. #include <alloc.h>
  6. #include <dir.h>
  7. #include "convdefs.h"
  8.  
  9.  
  10. char filenames[20000];
  11.  
  12. /*
  13. Here is the standard object storage protocol for files produced or loaded
  14. using the VECEDIT vector editing program.  The standard file extension
  15. for VECEDIT objects is ".VEC"
  16.  
  17.  
  18. POINTS
  19.    unsigned =number of raw points in object, if zero, terminate with error
  20.    array of long =raw points of object, stored {X,Y,Z}, {X,Y,Z} etc.
  21.  
  22. GROUP POINTS
  23.    unsigned =number of group points in object, if zero, ignore following
  24.    array of long =group points of object, stored {X,Y,Z} etc.
  25.  
  26. POLYGONS
  27.    unsigned =number of polygons in object, if zero, terminate with error
  28.    group of polygons stored as follows:
  29.       {
  30.       unsigned char =color value
  31.       unsigned =normvecoff (a multiple of 12, of course)
  32.       unsigned =pointoff (a multiple of 12, of course)
  33.       unsigned =group point "zee" offset corresponding to poly
  34.       }
  35.  
  36. NULL POLY
  37.    unsigned =offset in file used to refer to a null poly (from edgelist)
  38.  
  39. NORMALS
  40.    unsigned =number of normals in object
  41.    array of long =normals of polygons, stored {X,Y,Z}, {X,Y,Z}
  42.  
  43. EDGES
  44.    unsigned =number of edges in object, if zero, ignore following
  45.    group of edges stored as follows:
  46.       {
  47.       unsigned[2] =normalized vertex offsets (multiple of 8, from zero)
  48.       unsigned[2] =polygon offsets (multiple of 16, offset from zero)
  49.       }
  50.  
  51. */
  52.  
  53.  
  54. // read a 3D object in the above format from a file
  55.  
  56. void readobj3d(FILE *infile, numstuff *abc, unsigned *numgrps, unsigned *numnorms, unsigned nullpoly, long *rawpt, long *grppt, unsigned *grplist, polystruc *locpoly, long *rawnorms, rawedgeverts *edgees)
  57. {
  58. unsigned count, locdumpoly;
  59. unsigned *tempptr;
  60. int tempint;
  61.  
  62. // raw points
  63.    abc[0].vs=getw(infile);
  64.    if(abc[0].vs>0)
  65.       {
  66.       tempptr= (unsigned *) rawpt;
  67.       for(count=0;count<=(abc[0].vs)*6-1;count++)
  68.      {
  69.      tempptr[count]=getw(infile);
  70.      }
  71.       }
  72.  
  73. // group points
  74.    numgrps[0]=getw(infile);
  75.    if(numgrps[0]>0)
  76.       {
  77.       tempptr= (unsigned *) grppt;
  78.       for(count=0;count<=numgrps[0]*6-1;count++)
  79.      {
  80.      tempptr[count]=getw(infile);
  81.      }
  82.       }
  83.  
  84. // polygons
  85.    abc[0].ps=getw(infile);
  86.    if(abc[0].ps>0)
  87.       for(count=0;count<=abc[0].ps-1;count++)
  88.      {
  89.      locpoly[count].colorvalue=getc(infile);
  90.      locpoly[count].normvecoff=getw(infile);
  91.      locpoly[count].point     =getw(infile);
  92.      locpoly[count].texflag=0;
  93.      if(numgrps[0]>0)
  94.         {
  95.         grplist[count]=getw(infile);
  96.         }
  97.      else
  98.         {
  99.         getw(infile);
  100.         }
  101.      }
  102.  
  103. // null polygon
  104.    locdumpoly=getw(infile);
  105.  
  106. // normals
  107.    numnorms[0]=getw(infile);
  108.    if(numnorms[0]>0)
  109.       {
  110.       for(count=0;count<=numnorms[0]*3-1;count++)
  111.      {
  112.      tempint=getw(infile);
  113.      rawnorms[count]=tempint;
  114.      }
  115.       }
  116.  
  117. // edges
  118.    abc[0].es=getw(infile);
  119.    if(abc[0].es>0)
  120.       for(count=0;count<=abc[0].es-1;count++)
  121.      {
  122.      edgees[count].v[0]   =getw(infile);
  123.      edgees[count].v[1]   =getw(infile);
  124.  
  125.      edgees[count].poly[0]=getw(infile);
  126.      if(edgees[count].poly[0]==locdumpoly)
  127.         {
  128.         edgees[count].poly[0]=nullpoly;
  129.         }
  130.      else
  131.         {
  132.         edgees[count].poly[0]+=FP_OFF(locpoly);
  133.         }
  134.  
  135.      edgees[count].poly[1]=getw(infile);
  136.      if(edgees[count].poly[1]==locdumpoly)
  137.         {
  138.         edgees[count].poly[1]=nullpoly;
  139.         }
  140.      else
  141.         {
  142.         edgees[count].poly[1]+=FP_OFF(locpoly);
  143.         }
  144.  
  145.      edgees[count].texpoint[0]=0xFFFF;
  146.      edgees[count].texpoint[1]=0xFFFF;
  147.      }
  148.  
  149. }
  150.  
  151.  
  152.  
  153. /*
  154.  
  155. TEXTURE BITMAPS
  156.    Bitmaps are stored as follows, with 0xFFFF being the terminating number
  157.       {
  158.       unsigned  =number of texture polys
  159.       unsigned  =x size of bitmap
  160.       unsigned  =y size of bitmap
  161.       char array=characters that make up bitmap
  162.  
  163.       texture polys stored as follows:
  164.      {
  165.      unsigned  =pointer back to polygon
  166.      texture edges stored as follows, 0xFFFF terminates texture edges
  167.         {
  168.         unsigned =back pointer to edgee
  169.         unsigned =x corner 1
  170.         unsigned =y corner 1
  171.         unsigned =x corner 2
  172.         unsigned =y corner 2
  173.         }
  174.      }
  175.       }
  176.  
  177. GOURAD TEXTURE POLYS
  178.    stored as follows, with 0xFFFF being the terminator
  179.       {
  180.       unsigned =back pointer to polygon
  181.       texedges stored as follows, with 0xFFFF being the terminating number
  182.      {
  183.      unsigned =back pointer to edge array
  184.      unsigned =goustruc pointer[0] (offset from zero)
  185.      unsigned =goustruc pointer[1] (offset from zero)
  186.      }
  187.       }
  188.  
  189.  
  190. GOURAD VERTS
  191.    unsigned =number of gourad vertices
  192.    group of gourad verts stored as follows:
  193.       {
  194.       int      =gvalue
  195.       unsigned =vertoff (multiple of 12, offset from zero)
  196.       unsigned =vertnormoff (multiple of 12, offset from zero)
  197.       }
  198.  
  199. VERTEX NORMALS
  200.    unsigned =number of vertex normals
  201.    array of long =vertex normals, stored {X,Y,Z}, etc.
  202.  
  203.  
  204. */
  205.  
  206.  
  207. // Reads 3D texture information from a file in the above format
  208.  
  209. void readtexture3D(FILE *infile, rawedgeverts *edgees, polystruc *locpoly, texedge *texed, texstats *texts, texpoly *goutexpolys, unsigned char *bitmaparr[], unsigned *bitmapsizearray, texpoly *texpoarr[], unsigned *texpolused, unsigned *texpoltotal, gouvert *somegous, long *vertnorm, unsigned *numbmap, numstuff abc, numgoustuff *xyz)
  210. {
  211. unsigned count, ct2, ct3, ct4;
  212. unsigned lastbitmapread, lasttexpolyread, lasttexedgeread, shortdum;
  213. unsigned polyback, edgeback;
  214.  
  215. unsigned char *tempcharptr;
  216.  
  217. unsigned *tempintptr;
  218. unsigned *intpointy;
  219. texpoly *tempptr;
  220.  
  221.  
  222.    xyz[0].te=0;
  223.    xyz[0].tp=0;
  224.    xyz[0].vn=0;
  225.  
  226.  
  227. // TEXTURE BITMAP LOOP
  228.  
  229.    numbmap[0]=0;
  230.    lastbitmapread=getw(infile);
  231.  
  232.    while(lastbitmapread!=0xFFFF)
  233.       {
  234.       // read in size of texture map
  235.  
  236.       bitmapsizearray[numbmap[0]*2  ]=getw(infile);
  237.       bitmapsizearray[numbmap[0]*2+1]=getw(infile);
  238.  
  239.       // Allocate memory for bitmap array and texture polys
  240.  
  241.       if ((bitmaparr[numbmap[0]] = (char *) malloc(10 + bitmapsizearray[numbmap[0]*2]*bitmapsizearray[numbmap[0]*2+1] + 26*(lastbitmapread+10) )) == NULL)
  242.      {
  243.      cprintf("Not enough memory to allocate buffer\n\r");
  244.      getch();
  245.      return;
  246.      }
  247.  
  248.       // set up texpoly pointer and set up texture map size info
  249.  
  250.       texpoarr[numbmap[0]] =(texpoly *) MK_FP(FP_SEG(bitmaparr[numbmap[0]]),FP_OFF(bitmaparr[numbmap[0]]) + 10 + bitmapsizearray[numbmap[0]*2]*bitmapsizearray[numbmap[0]*2 + 1]);
  251.       count=0;
  252.       shortdum=bitmapsizearray[numbmap[0]*2];
  253.       while(shortdum>1)
  254.      {
  255.      count++;
  256.      shortdum/=2;
  257.      }
  258.       intpointy= (unsigned *) bitmaparr[numbmap[0]];
  259.       intpointy[0]=count;
  260.       intpointy[1]=-1;
  261.       intpointy[2]=-1<<count;
  262.  
  263.       // set up used and total array
  264.  
  265.       texpolused[numbmap[0]]=lastbitmapread;
  266.       texpoltotal[numbmap[0]]=lastbitmapread+10;
  267.  
  268.       // read characters of bitmap
  269.  
  270.       tempcharptr=bitmaparr[numbmap[0]];
  271.       for(count=0; count<bitmapsizearray[numbmap[0]*2]*bitmapsizearray[numbmap[0]*2+1]; count++)
  272.      {
  273.      tempcharptr[count+6]=getc(infile);
  274.      }
  275.  
  276.  
  277.       // get texture polys (there are "lastbitmapread" of them)
  278.       for(count=0; count<lastbitmapread; count++)
  279.      {
  280.      // set up ordinary polygon
  281.      polyback=getw(infile)/16;
  282.      locpoly[polyback].texflag=1;
  283.      locpoly[polyback].texpoly=MK_FP(FP_SEG(texpoarr[numbmap[0]]), FP_OFF(texpoarr[numbmap[0]]) + count*26);
  284.  
  285.      // set up texture poly (texture pointer and edgesgot)
  286.      tempptr=(texpoly *) locpoly[polyback].texpoly;
  287.      tempptr[0].texture= FP_OFF(bitmaparr[numbmap[0]]);
  288.      tempptr[0].edgesgot= 0;
  289.  
  290.      // loop to read texture edges
  291.      lasttexedgeread= getw(infile);
  292.      while(lasttexedgeread!=0xFFFF)
  293.         {
  294.         // set up edge back reference
  295.         edgeback=lasttexedgeread/12;
  296.         if(edgees[edgeback].texpoint[0]==0xFFFF)
  297.            {
  298.            edgees[edgeback].texpoint[0]=xyz[0].te*32 + FP_OFF(texed);
  299.            }
  300.         else
  301.            {
  302.            edgees[edgeback].texpoint[1]=xyz[0].te*32 + FP_OFF(texed);
  303.            }
  304.  
  305.         // set up texture poly, edgeflag, and statloc
  306.         texed[xyz[0].te].texpo=locpoly[polyback].texpoly;
  307.         texed[xyz[0].te].edgeflag=1;
  308.         texed[xyz[0].te].statloc=xyz[0].te*16 + FP_OFF(texts);
  309.  
  310.         // set up texture statistics
  311.         texts[xyz[0].te].xcorn1=getw(infile);
  312.         texts[xyz[0].te].ycorn1=getw(infile);
  313.         texts[xyz[0].te].xcorn2=getw(infile);
  314.         texts[xyz[0].te].ycorn2=getw(infile);
  315.         texts[xyz[0].te].xmax=bitmapsizearray[numbmap[0]*2  ];
  316.         texts[xyz[0].te].ymax=bitmapsizearray[numbmap[0]*2+1];
  317.  
  318.         // increment counters and keep going
  319.         xyz[0].te++;
  320.         lasttexedgeread=getw(infile);
  321.         }
  322.      }
  323.  
  324.       numbmap[0]++;
  325.       lastbitmapread=getw(infile);
  326.       }
  327.  
  328.  
  329. // GOURAD TEXTURE POLY LOOP
  330.  
  331.    lasttexpolyread=getw(infile);
  332.  
  333.    while(lasttexpolyread!=0xFFFF)
  334.       {
  335.       // set up ordinary polygon
  336.       polyback=lasttexpolyread/16;
  337.       locpoly[polyback].texflag=1;
  338.       locpoly[polyback].texpoly=(void *) &goutexpolys[xyz[0].tp];
  339.  
  340.       // set up texture poly (edgesgot)
  341.       goutexpolys[xyz[0].tp].edgesgot= 0;
  342.  
  343.       // loop to read texture edges
  344.       lasttexedgeread= getw(infile);
  345.       while(lasttexedgeread!=0xFFFF)
  346.      {
  347.      // set up edge back reference
  348.      edgeback=lasttexedgeread/12;
  349.      if(edgees[edgeback].texpoint[0]==0xFFFF)
  350.         {
  351.         edgees[edgeback].texpoint[0]=xyz[0].te*32 + FP_OFF(texed);
  352.         }
  353.      else
  354.         {
  355.         edgees[edgeback].texpoint[1]=xyz[0].te*32 + FP_OFF(texed);
  356.         }
  357.  
  358.      // set up texture poly, edgeflag, and statloc
  359.      texed[xyz[0].te].texpo=locpoly[polyback].texpoly;
  360.      texed[xyz[0].te].edgeflag=2;
  361.      texed[xyz[0].te].statloc=xyz[0].te*16 + FP_OFF(texts);
  362.  
  363.      // get goustruc pointers
  364.      texts[xyz[0].te].goustruc[0]=getw(infile) + FP_OFF(somegous);
  365.      texts[xyz[0].te].goustruc[1]=getw(infile) + FP_OFF(somegous);
  366.  
  367.      // increment counters and keep going
  368.      xyz[0].te++;
  369.      lasttexedgeread=getw(infile);
  370.      }
  371.  
  372.       // increment counters and keep going
  373.       xyz[0].tp++;
  374.       lasttexpolyread=getw(infile);
  375.       }
  376.  
  377.  
  378. // Load some gourad vertices
  379.  
  380.    xyz[0].vn=getw(infile);
  381.    for(count=0; count<xyz[0].vn; count++)
  382.       {
  383.       somegous[count].gvalue=getw(infile);
  384.       somegous[count].vertoff=getw(infile);
  385.       somegous[count].vertnormoff=getw(infile);
  386.       }
  387.  
  388. // Load some vertex normals
  389.  
  390.    getw(infile);
  391.    tempintptr= (unsigned *) vertnorm;
  392.    for(count=0; count<xyz[0].vn*6; count++)
  393.       {
  394.       tempintptr[count]=getw(infile);
  395.       }
  396.  
  397. // DONE AT LAST !!!!!!!!!!!!!!!!!!!!!!
  398.  
  399. }
  400.  
  401.  
  402.  
  403. /*
  404. The following function is used to load and save 3D objects from a group
  405. of files.  The files are all assumed to have an extension of ".VEC".
  406. The program asks for a directory to search for the files in and then
  407. displays all objects and files that can be loaded.
  408. The up and down arrow keys can be used to highlight objects, and enter
  409. will load objects.  In the save objects mode, a list of all current
  410. objects is shown and the user can create a new file.
  411.  
  412. NOTE: FILENAMES MAY NOT BE MORE THAN 40 CHARACTERS
  413.       THE LIMIT TO NUMBER OF OBJECTS IN A DIRECTORY IS 500
  414. */
  415.  
  416.  
  417. void load3D(numstuff *abc, unsigned *numgrps, unsigned *numnorms, unsigned nullpoly, long *rawpt, long *grppt, unsigned *grplist, polystruc *locpoly, long *rawnorms, rawedgeverts *edgees, texedge *texed, texstats *texts, texpoly *goutexpolys, unsigned char *bitmaparr[], unsigned *bitmapsizearray, gouvert *somegous, long *vertnorm, unsigned *numbmap, numgoustuff *xyz, unsigned *texpolused, unsigned *texpoltotal, texpoly *texpoarr[])
  418. {
  419. char maincommand;    // used to accept commands
  420.  
  421. FILE *currfile;        // thingy used for files
  422. char searchdir[40];    // search directory for loading
  423. unsigned numfound;    // number of 3D object files found
  424. unsigned count, screenoff=0, highlight=0;
  425. unsigned shortdum;
  426. char *tempfilename;
  427.  
  428. struct ffblk ffblk;
  429. int done;
  430. numstuff    abcextra;
  431. unsigned grpsextra, normsextra;
  432.  
  433.  
  434.    clrscr();
  435.    // LOAD OPERATIONS
  436.  
  437.    cprintf("Which directory shall I search, master?\n\n\r");
  438.    cprintf("Input search path-->");
  439.    gets(searchdir);
  440.    count=0;
  441.    while(searchdir[count]!=0) count++;
  442.       if((count!=0)&&(searchdir[count-1]!='\\'))
  443.      {
  444.      searchdir[count]='\\';
  445.      count++;
  446.      }
  447.       searchdir[count  ]='*';
  448.       searchdir[count+1]='.';
  449.       searchdir[count+2]='V';
  450.       searchdir[count+3]='E';
  451.       searchdir[count+4]='C';
  452.       searchdir[count+5]=0;
  453.  
  454.       cprintf("\n\rSearching for files...\n\r");
  455.       done = findfirst(searchdir,&ffblk,0);
  456.       if(done!=0) { cprintf("No files found, dumbass.\n\rPress a key."); getch(); goto deallocit;}
  457.       cprintf("Loading filenames...\n\r");
  458.       numfound=0;
  459.       while (!done)
  460.      {
  461.      sprintf(&filenames[numfound*40],"%s",searchdir);
  462.      sprintf(&filenames[numfound*40 + count],"%s",ffblk.ff_name);
  463.      numfound++;
  464.      done = findnext(&ffblk);
  465.      }
  466.  
  467. updateload:
  468. ;
  469.       clrscr();
  470.       cprintf("Highlight object to load and press enter");
  471.  
  472.       for(count=0;count<=23;count++)
  473.      {
  474.      if((count+screenoff)==numfound) count=25;
  475.         else
  476.            {
  477.            if(highlight==count) textattr(0x70);
  478.            cprintf("\n\r%2d.  %Fs",count+screenoff,&filenames[(count+screenoff)*40]);
  479.            if(highlight==count) textattr(0x07);
  480.            }
  481.      }
  482.  
  483. getakeyload:
  484. ;
  485.       maincommand=getch();
  486.       if((maincommand>='a')&&(maincommand<='z')) maincommand=maincommand-'a'+'A';
  487.       if((maincommand<='9')&&(maincommand>='0'))
  488.      {
  489.      if(numfound>(maincommand-'0')*10)
  490.         {
  491.         highlight=maincommand-'0';
  492.         highlight*=10;
  493.         screenoff=0;
  494.         while(highlight>23)
  495.            {
  496.            highlight-=24;
  497.            screenoff+=24;
  498.            }
  499.         }
  500.      goto updateload;
  501.      }
  502.       else
  503.       switch(maincommand)
  504.      {
  505.      case  13:{
  506.           if ((currfile=fopen(&filenames[(highlight+screenoff)*40],"rb")) != NULL)
  507.              {
  508.              readobj3d(currfile, abc, numgrps, numnorms, nullpoly, rawpt, grppt, grplist, locpoly, rawnorms, edgees);
  509.              fclose(currfile);
  510.  
  511.              tempfilename=&filenames[(highlight+screenoff)*40];
  512.              shortdum=0;
  513.              while(tempfilename[shortdum]!='.') shortdum++;
  514.              tempfilename[shortdum+1]='T';
  515.              tempfilename[shortdum+3]='X';
  516.  
  517.              if ((currfile=fopen(&filenames[(highlight+screenoff)*40],"rb")) != NULL)
  518.             {
  519.             readtexture3D(currfile, edgees, locpoly, texed, texts, goutexpolys, bitmaparr, bitmapsizearray, texpoarr, texpolused, texpoltotal, somegous, vertnorm, numbmap, abc[0], xyz);
  520.             fclose(currfile);
  521.             cprintf("\n\n\rFile AND TEXTURE successfully loaded\n\rPress a key.\n\r");
  522.             getch();
  523.             }
  524.              else
  525.             {
  526.             cprintf("\n\n\rFile successfully loaded\n\rPress a key.\n\r");
  527.             getch();
  528.             }
  529.  
  530.              tempfilename[shortdum+1]='V';
  531.              tempfilename[shortdum+3]='C';
  532.              }
  533.           else
  534.              {
  535.              cprintf("\n\n\rError opening file\n\rPress a key.\n\r");
  536.              getch();
  537.              }
  538.           goto updateload;
  539.           }
  540.  
  541.      case  27:
  542.      case 'Q':
  543.      case 'X':{
  544.           return;
  545.           }
  546.  
  547.      case  0 :{
  548.           maincommand=getch();
  549.           if((maincommand=='P')&&((highlight+screenoff)<numfound-1))
  550.              {
  551.              highlight++;
  552.              if(highlight>23)
  553.             {
  554.             highlight=0;
  555.             screenoff+=24;
  556.             }
  557.              goto updateload;
  558.              }
  559.           if((maincommand=='H')&&((highlight+screenoff)>0))
  560.              {
  561.              if(highlight==0)
  562.             {
  563.             highlight=24;
  564.             screenoff-=24;
  565.             }
  566.              highlight--;
  567.              goto updateload;
  568.              }
  569.           if((maincommand==73)&&(screenoff>0))
  570.              {
  571.              // Page up
  572.              screenoff-=24;
  573.              highlight=0;
  574.              goto updateload;
  575.              }
  576.           if((maincommand==81)&&((screenoff+24)<numfound-1))
  577.              {
  578.              // Page down
  579.              screenoff+=24;
  580.              highlight=0;
  581.              goto updateload;
  582.              }
  583.           goto getakeyload;
  584.           }
  585.  
  586.      default :goto getakeyload;
  587.      }
  588.  
  589. deallocit:
  590. ;
  591.  
  592.  
  593. }
  594.  
  595.  
  596. // calculates a dot b
  597.  
  598. long dotproduct(long *a, long *b)
  599. {
  600.    long returnval;
  601.    returnval=a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
  602.    return(returnval);
  603. }
  604.  
  605.  
  606. // calculates x dot (a cross b)-- the triple scalar product
  607. // only the sign is accurate, though
  608.  
  609. float triplescalar(long *x, long *a, long *b)
  610. {
  611. float returnval, vec[3], x2[3], a2[3], b2[3];
  612. unsigned count;
  613.  
  614.    for(count=0; count<=2; count++) x2[count]= x[count];
  615.    for(count=0; count<=2; count++) a2[count]= a[count];
  616.    for(count=0; count<=2; count++) b2[count]= b[count];
  617.    vec[0]= ((a2[1]*b2[2]) - (a2[2]*b2[1]));
  618.    vec[1]=-((a2[0]*b2[2]) - (a2[2]*b2[0]));
  619.    vec[2]= ((a2[0]*b2[1]) - (a2[1]*b2[0]));
  620.    returnval= x[0]*vec[0] + x[1]*vec[1] + x[2]*vec[2];
  621.  
  622. return(returnval);
  623. }
  624.  
  625.  
  626. // Calculates the magnitude of a given vector.  Might modify the magnitude
  627. // of the given vector to prevent nasty overflow errors.  The function
  628. // will return the magnitude of the resulting vector regardless.
  629.  
  630. long magnitude(long *a)
  631. {
  632. unsigned ct2;
  633. long returnval, mag, sqrtmag;
  634.  
  635.    while((a[0]>32768) || (a[1]>32768) || (a[2]>32768) || (a[0]<-32768) || (a[1]<-32768) || (a[2]<-32768))
  636.       {
  637.       a[0]/=2;
  638.       a[1]/=2;
  639.       a[2]/=2;
  640.       }
  641.  
  642.    mag = (a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
  643.    if(mag==0) return(0);
  644.  
  645.    if(mag<33554432l)
  646.       {
  647.       mag*=16;
  648.       a[0]*=4;
  649.       a[1]*=4;
  650.       a[2]*=4;
  651.       }
  652.    sqrtmag= mag/2;
  653.    for(ct2=1;ct2<=20;ct2++)
  654.       {
  655.       sqrtmag= (sqrtmag + mag/sqrtmag)/2;
  656.       }
  657.  
  658.    returnval=sqrtmag+1;
  659.  
  660. return(returnval);
  661.  
  662. }
  663.  
  664.  
  665. // normalize a vector to 512, the standard norm size
  666.  
  667. void normalize(long *a, long magnitude)
  668. {
  669. unsigned count;
  670.  
  671.    for(count=0;count<=2;count++)
  672.       {
  673.       a[count]=(a[count]*512)/magnitude;
  674.       }
  675.  
  676. }
  677.  
  678.  
  679. //************************************************************************
  680. //************************************************************************
  681. // The following routine calculates the set of vertices for a face.
  682. // The offset for "faceverts" is the actual offset to put the info.  The
  683. // other three arrays are all offset from zero.  This routine sets up
  684. // everything except texture information.
  685.  
  686. void setupface(unsigned num, polystruc *polys, rawedgeverts *edgees, unsigned *grplist, long *rawpt, long *norms, face *thefaces, unsigned *faceverts, numstuff abc)
  687. {
  688. unsigned count, ct2, lastedge, vertloc=0, temp;
  689. long vec1[3], vec2[3];
  690.  
  691. // calculate the number of points and get the location of one point
  692.  
  693. thefaces[num].numpoints=0;
  694. for(count=0; count<abc.es; count++)
  695.    {
  696.    if(edgees[count].poly[0]==(num*16 + FP_OFF(polys)))
  697.       {
  698.       thefaces[num].numpoints++;        // one point per edge
  699.       faceverts[0]=edgees[count].v[0]/8;    // store a point
  700.       }
  701.    if(edgees[count].poly[1]==(num*16 + FP_OFF(polys)))
  702.       {
  703.       thefaces[num].numpoints++;                // one point per edge
  704.       faceverts[0]=edgees[count].v[0]/8;    // store a point
  705.       }
  706.    }
  707. thefaces[num].pointarray=faceverts;        // set up the pointarray
  708. thefaces[num].color=polys[num].colorvalue;    // set up color value
  709. thefaces[num].normalvec=polys[num].normvecoff/12;    // set up normal vec
  710. thefaces[num].shadeflag=0;            // shading flag
  711. thefaces[num].grouppt=grplist[num]/12;        // group point
  712.  
  713. lastedge=abc.es+1;                // set the last edge
  714.  
  715. // seek the next point and write it until the next point==original point
  716. do {
  717.    vertloc++;
  718.    // seek an edge!=lastedge that contains faceverts[vertloc-1] AND the poly
  719.    for(count=0; count<abc.es; count++)
  720.       {
  721.       if(count!=lastedge)
  722.      {
  723.      if((edgees[count].v[0]==faceverts[vertloc-1]*8)&&((edgees[count].poly[0]==num*16+FP_OFF(polys)) || (edgees[count].poly[1]==num*16+FP_OFF(polys))))
  724.         {
  725.         faceverts[vertloc]=edgees[count].v[1]/8;
  726.         lastedge=count;
  727.         count=abc.es+1;
  728.         }
  729.      else
  730.      if((edgees[count].v[1]==faceverts[vertloc-1]*8)&&((edgees[count].poly[0]==num*16+FP_OFF(polys)) || (edgees[count].poly[1]==num*16+FP_OFF(polys))))
  731.         {
  732.         faceverts[vertloc]=edgees[count].v[0]/8;
  733.         lastedge=count;
  734.         count=abc.es+1;
  735.         }
  736.      }
  737.       }
  738.    if(kbhit()) {getch(); return;}
  739.    } while(faceverts[vertloc]!=faceverts[0]);
  740.  
  741. // Fix the normals of the face for the "right hand rule"
  742.  
  743. startover:
  744.    vec1[0]= rawpt[thefaces[num].pointarray[0]*3 + 0] - rawpt[thefaces[num].pointarray[1]*3 + 0];
  745.    vec1[1]= rawpt[thefaces[num].pointarray[0]*3 + 1] - rawpt[thefaces[num].pointarray[1]*3 + 1];
  746.    vec1[2]= rawpt[thefaces[num].pointarray[0]*3 + 2] - rawpt[thefaces[num].pointarray[1]*3 + 2];
  747.  
  748.    vec2[0]= rawpt[thefaces[num].pointarray[2]*3 + 0] - rawpt[thefaces[num].pointarray[1]*3 + 0];
  749.    vec2[1]= rawpt[thefaces[num].pointarray[2]*3 + 1] - rawpt[thefaces[num].pointarray[1]*3 + 1];
  750.    vec2[2]= rawpt[thefaces[num].pointarray[2]*3 + 2] - rawpt[thefaces[num].pointarray[1]*3 + 2];
  751.  
  752.    // check to see if the vectors are collinear
  753.    normalize(vec1, magnitude(vec1));
  754.    normalize(vec2, magnitude(vec2));
  755.    if(dotproduct(vec1, vec2)<-250000l)
  756.       {
  757.       // if so, scramble the points and recalc
  758.       temp=thefaces[num].pointarray[0];
  759.       for(ct2=0; ct2<thefaces[num].numpoints-1; ct2++)
  760.      {
  761.      thefaces[num].pointarray[ct2]=thefaces[num].pointarray[ct2 + 1];
  762.      }
  763.       thefaces[num].pointarray[thefaces[num].numpoints-1]=temp;
  764.       asm jmp startover;
  765.       }
  766.  
  767.    // check points with the normal vector
  768.    if(triplescalar(&norms[thefaces[num].normalvec*3], vec2, vec1)<0)
  769.       {
  770.       // scramble the points again and we are done.
  771.       temp=thefaces[num].pointarray[0];
  772.       thefaces[num].pointarray[0]=thefaces[num].pointarray[2];
  773.       thefaces[num].pointarray[2]=temp;
  774.       for(ct2=0; ct2<(thefaces[num].numpoints-3)/2; ct2++)
  775.      {
  776.      temp=thefaces[num].pointarray[ct2+3];
  777.      thefaces[num].pointarray[ct2+3]=thefaces[num].pointarray[thefaces[num].numpoints-ct2-1];
  778.      thefaces[num].pointarray[thefaces[num].numpoints-ct2-1]=temp;
  779.      }
  780.       }
  781.  
  782. }
  783.  
  784.  
  785. //************************************************************************
  786. //************************************************************************
  787. // The following routine calculates the texture interpolation information
  788. // for doing texture mapping and gourad shading.
  789.  
  790. void setuptexture(unsigned num, polystruc *polys, rawedgeverts *edgees, face *thefaces, numstuff abc, texedge *texed, texstats *texts, gouvert *somegous, outgou *thegous, outtex *thetexs)
  791. {
  792. unsigned count, ct2;
  793. texpoly *txp;
  794. texedge *txe;
  795. texstats *txs;
  796.  
  797. txp=((texpoly *) polys[num].texpoly);
  798.  
  799. thefaces[num].gouvee= thegous;
  800. thefaces[num].texvee= thetexs;
  801.  
  802. // Loop through all the vertices connected to the poly
  803. for(count=0; count<thefaces[num].numpoints; count++)
  804.    {
  805.    // Search for an edge that contains the vertex
  806.    for(ct2=0; ct2<abc.es; ct2++)
  807.       {
  808.       if((thefaces[num].pointarray[count]==edgees[ct2].v[0]/8)&&((edgees[ct2].poly[0]==num*16+FP_OFF(polys)) || (edgees[ct2].poly[1]==num*16+FP_OFF(polys))))
  809.      {
  810.      // found a vertex...
  811.      // set up our temp pointer to the texture edge
  812.      if((edgees[ct2].texpoint[0]!=0xFFFF)&&(txp==texed[(edgees[ct2].texpoint[0]-FP_OFF(texed))/32].texpo))
  813.         {
  814.         txe=&texed[(edgees[ct2].texpoint[0]-FP_OFF(texed))/32];
  815.         }
  816.      else
  817.         {
  818.         txe=&texed[(edgees[ct2].texpoint[1]-FP_OFF(texed))/32];
  819.         }
  820.      txs=&texts[(txe[0].statloc-FP_OFF(texts))/16];
  821.  
  822.      // the first time through, get bitmap/ shadeflag information
  823.      if(count==0)
  824.         {
  825.         thefaces[num].shadeflag=txe[0].edgeflag;
  826.         if(thefaces[num].shadeflag==1)
  827.            {
  828.            thefaces[num].bmp= (char *) MK_FP(FP_SEG(txp), txp[0].texture);
  829.            }
  830.         }
  831.  
  832.      // Set up the rest of the information
  833.      if(thefaces[num].shadeflag==1)
  834.         {
  835.         thetexs[count].x=txs[0].xcorn1;
  836.         thetexs[count].y=txs[0].ycorn1;
  837.         }
  838.      else
  839.         {
  840.         thegous[count].vertnormal=somegous[(txs[0].goustruc[0]-FP_OFF(somegous))/6].vertnormoff/12;
  841.         }
  842.  
  843.      ct2=abc.es+1;
  844.      }
  845.       if((thefaces[num].pointarray[count]==edgees[ct2].v[1]/8)&&((edgees[ct2].poly[0]==num*16+FP_OFF(polys)) || (edgees[ct2].poly[1]==num*16+FP_OFF(polys))))
  846.      {
  847.      // found a vertex...
  848.      // set up our temp pointer to the texture edge
  849.      if((edgees[ct2].texpoint[0]!=0xFFFF)&&(txp==texed[(edgees[ct2].texpoint[0]-FP_OFF(texed))/32].texpo))
  850.         {
  851.         txe=&texed[(edgees[ct2].texpoint[0]-FP_OFF(texed))/32];
  852.         }
  853.      else
  854.         {
  855.         txe=&texed[(edgees[ct2].texpoint[1]-FP_OFF(texed))/32];
  856.         }
  857.      txs=&texts[(txe[0].statloc-FP_OFF(texts))/16];
  858.  
  859.      // the first time through, get bitmap/ shadeflag information
  860.      if(count==0)
  861.         {
  862.         thefaces[num].shadeflag=txe[0].edgeflag;
  863.         if(thefaces[num].shadeflag==1)
  864.            {
  865.            thefaces[num].bmp= (char *) MK_FP(FP_SEG(txp), txp[0].texture);
  866.            }
  867.         }
  868.  
  869.      // Set up the rest of the information
  870.      if(thefaces[num].shadeflag==1)
  871.         {
  872.         thetexs[count].x=txs[0].xcorn2;
  873.         thetexs[count].y=txs[0].ycorn2;
  874.         }
  875.      else
  876.         {
  877.         thegous[count].vertnormal=somegous[(txs[0].goustruc[1]-FP_OFF(somegous))/6].vertnormoff/12;
  878.         }
  879.      ct2=abc.es+1;
  880.      }
  881.       }
  882.    }
  883. }
  884.  
  885.  
  886. //************************************************************************
  887. //************************************************************************
  888. // Converts the 3D objects to a "simpler" format.
  889.  
  890. void conv3D(numstuff *abc, long *rawpt, unsigned *grplist, polystruc *locpoly, long *rawnorms, rawedgeverts *edgees, texedge *texed, texstats *texts, gouvert *somegous, numgoustuff *xyz, face *thefaces, outgou *thegous, outtex *thetexs, unsigned *faceverts)
  891. {
  892. unsigned count, ct2, facevertoffs=0, tvertoffs=0, gvertoffs=0;
  893.  
  894. clrscr();
  895. // Figure out the faces and the faceverts list (this is the hardest part)
  896. for(count=0; count<abc[0].ps; count++)
  897.    {
  898.    setupface(count, locpoly, edgees, grplist, rawpt, rawnorms, thefaces, &faceverts[facevertoffs], abc[0]);
  899.    facevertoffs+=thefaces[count].numpoints;
  900.    }
  901.  
  902. // Figure out stuff for texture mapping
  903. if(xyz[0].te>0) for(count=0; count<abc[0].ps; count++)
  904.    {
  905.    if(locpoly[count].texflag==1)
  906.       {
  907.       setuptexture(count, locpoly, edgees, thefaces, abc[0], texed, texts, somegous, thegous, thetexs);
  908.       tvertoffs+=thefaces[count].numpoints;
  909.       gvertoffs+=thefaces[count].numpoints;
  910.       }
  911.  
  912.    cprintf("%d,  ", thefaces[count].numpoints);
  913.    for(ct2=0; ct2<thefaces[count].numpoints; ct2++)
  914.       {
  915.       cprintf("%d, ", thefaces[count].pointarray[ct2]);
  916.       }
  917.    cprintf(" %d,  ", (thefaces[count].color&3)+1);
  918.    if(thefaces[count].shadeflag==1)
  919.       {
  920.       cprintf("Texture map:  ");
  921.       }
  922.    else
  923.       {
  924.       cprintf("Vertex normals:  ");
  925.       }
  926.    for(ct2=0; ct2<thefaces[count].numpoints; ct2++)
  927.       {
  928.       if(thefaces[count].shadeflag==1)
  929.      {
  930.      cprintf("{%d,%d}, ",thefaces[count].texvee[ct2].x, thefaces[count].texvee[ct2].y);
  931.      }
  932.       else
  933.      {
  934.      cprintf("{%d}, ", thefaces[count].gouvee[ct2].vertnormal);
  935.      }
  936.       }
  937.    cprintf("\n\r");
  938.    if(getch()==27) count=abc[0].ps+1;
  939.    }
  940. }
  941.  
  942.  
  943.  
  944. //************************************************************************
  945. //************************************************************************
  946. // Test dump of 3D object for ved04b-- you can find ved04b on x2ftp.oulu.fi
  947.  
  948. void dumpved04(numstuff abc, long *rawpt, face *thefaces)
  949. {
  950. unsigned count, ct2;
  951. char *filename= "test.v04";
  952. FILE *out;
  953.  
  954. if ((out = fopen(filename, "wt"))== NULL)
  955.    {
  956.    fprintf(stderr, "Cannot open output file.\n");
  957.    return;
  958.    }
  959.  
  960. fprintf(out, "%d,\n", abc.vs);
  961.  
  962. for(count=0; count<abc.vs; count++)
  963.    {
  964.    fprintf(out, "%ld, %ld, %ld,\n", rawpt[count*3]/4, rawpt[count*3 + 1]/4, rawpt[count*3 + 2]/4);
  965.    }
  966. fprintf(out, "\n%d,\n", abc.ps);
  967. for(count=0; count<abc.ps; count++)
  968.    {
  969.    fprintf(out, "%d,  ", thefaces[count].numpoints);
  970.    for(ct2=0; ct2<thefaces[count].numpoints; ct2++)
  971.       {
  972.       fprintf(out, "%d, ", thefaces[count].pointarray[ct2]);
  973.       }
  974.    fprintf(out, " %d,\n", (thefaces[count].color&3)+1);
  975.    }
  976.  
  977. fclose(out);
  978. }
  979.  
  980.  
  981.